<!--
 * @Description: 第十章 认识watch侦听器
 * @Author: IA ia@kepro.space
 * @Date: 2025-02-12 15:59:59
-->
<template>
  <div>
    <p>watch</p>
    <div>
      <p>侦听单个值</p>
      <label>
        case1:
        <input v-model="case1" type="text" />
      </label>
      <label>
        case2:
        <input v-model="case2" type="text" />
      </label>
    </div>
    <hr />
    <div>
      <p>侦听Ref对象(未打开深度侦听)</p>
      <label>
        caseRefObjWithoutDeep name:
        <input v-model="caseRefObjWithoutDeep.info.name" type="text" />
      </label>
      <label>
        caseRefObjWithoutDeep age:
        <input v-model="caseRefObjWithoutDeep.info.age" type="text" />
      </label>
    </div>
    <hr />
    <div>
      <p>侦听Ref对象(已打开深度侦听)</p>
      <label>
        caseRefObjWithDeep name:
        <input v-model="caseRefObjWithDeep.info.name" type="text" />
      </label>
      <label>
        caseRefObjWithDeep age:
        <input v-model="caseRefObjWithDeep.info.age" type="text" />
      </label>
    </div>
    <hr />
    <div>
      <p>侦听Reactive对象(未打开深度侦听)</p>
      <label>
        caseReactiveObjWithoutDeep name:
        <input v-model="caseReactiveObjWithoutDeep.info.name" type="text" />
      </label>
      <label>
        caseReactiveObjWithoutDeep age:
        <input v-model="caseReactiveObjWithoutDeep.info.age" type="text" />
      </label>
    </div>
    <hr />
    <div>
      <p>侦听响应式对象的其中一个元素</p>
      <label>
        caseReactiveObjEle name:
        <input v-model="caseReactiveObjEle.info.name" type="text" />
      </label>
      <label>
        caseReactiveObjEle age:
        <input v-model="caseReactiveObjEle.info.age" type="text" />
      </label>
    </div>
    <hr />
    <div>
      <p>侦听响应式对象（初始化即执行）</p>
      <label>
        caseReactiveObjImmediate name:
        <input v-model="caseReactiveObjImmediate.info.name" type="text" />
      </label>
      <label>
        caseReactiveObjImmediate age:
        <input v-model="caseReactiveObjImmediate.info.age" type="text" />
      </label>
    </div>
    <hr />
    <div>
      <p>侦听响应式对象（组件执行顺序 flush）</p>
      <div>
        <p>flush pre 组件更新前执行</p>
        <label>
          caseRefObjFlushPre name:
          <input v-model="caseRefObjFlushPre.info.name" type="text" />
        </label>
        <label>
          caseRefObjFlushPre age:
          <input v-model="caseRefObjFlushPre.info.age" type="text" />
        </label>
      </div>
      <div>
        <p>flush sync 组件同步执行</p>
        <label>
          caseRefObjFlushSync name:
          <input v-model="caseRefObjFlushSync.info.name" type="text" />
        </label>
        <label>
          caseRefObjFlushSync age:
          <input v-model="caseRefObjFlushSync.info.age" type="text" />
        </label>
      </div>
      <div>
        <p>flush post 组件更新之后执行</p>
        <label>
          caseRefObjFlushPost name:
          <input v-model="caseRefObjFlushPost.info.name" type="text" />
        </label>
        <label>
          caseRefObjFlushPost age:
          <input v-model="caseRefObjFlushPost.info.age" type="text" />
        </label>
      </div>
    </div>
  </div>
</template>
<script setup lang="ts">
import { ref, reactive, watch } from 'vue'
/*
watch 需要侦听特定的数据源，并在单独的回调函数中执行副作用
watch第一个参数监听源
watch第二个参数回调函数cb（newVal,oldVal）
watch第三个参数一个options配置项是一个对象{
immediate:true //是否立即调用一次
deep:true //是否开启深度监听
}
*/

let case1 = ref<string>('大制作')

let case2 = ref<string>('诚意制作')

watch([case1, case2], (newVal, oldVal) => {
  console.log('[case1, case2] newVal: ', newVal)
  console.log('[case1, case2] oldVal: ', oldVal)
})

let caseRefObjWithoutDeep = ref({
  info: {
    name: 'IA',
    age: 100,
  },
})

watch(caseRefObjWithoutDeep, (newVal, oldVal) => {
  console.log('caseRefObjWithoutDeep newVal: ', newVal)
  console.log('caseRefObjWithoutDeep oldVal: ', oldVal)
})

let caseRefObjWithDeep = ref({
  info: {
    name: 'IA',
    age: 100,
  },
})

watch(
  caseRefObjWithDeep,
  (newVal, oldVal) => {
    console.log('caseRefObjWithDeep newVal: ', newVal)
    console.log('caseRefObjWithDeep oldVal: ', oldVal)
  },
  {
    deep: true, // 深度侦听
  },
)

let caseReactiveObjWithoutDeep = reactive({
  info: {
    name: 'IA',
    age: 100,
  },
})

watch(
  caseReactiveObjWithoutDeep,
  (newVal, oldVal) => {
    console.log('caseReactiveObjWithoutDeep newVal: ', newVal)
    console.log('caseReactiveObjWithoutDeep oldVal: ', oldVal)
  },
  {
    // deep: true, // 深度侦听 reactive已自定启用
  },
)

let caseReactiveObjEle = reactive({
  info: {
    name: 'IA',
    age: 100,
  },
})

watch(
  // 侦听源不能直接为 caseReactiveObjEle.info.age
  // 如果需要侦听元素，要使用函数形式return元素值
  () => caseReactiveObjEle.info.age,
  (newVal, oldVal) => {
    console.log('caseReactiveObjEle age newVal: ', newVal)
    console.log('caseReactiveObjEle age oldVal: ', oldVal)
  },
)

let caseReactiveObjImmediate = ref({
  info: {
    name: 'IA',
    age: 100,
  },
})

watch(
  caseReactiveObjImmediate,
  (newVal, oldVal) => {
    console.log('caseReactiveObjImmediate newVal: ', newVal)
    console.log('caseReactiveObjImmediate oldVal: ', oldVal)
  },
  {
    immediate: true, // 是否立即执行一次
  },
)

let caseRefObjFlushPre = reactive({
  info: {
    name: 'IA',
    age: 100,
  },
})
let caseRefObjFlushSync = reactive({
  info: {
    name: 'IA',
    age: 100,
  },
})
let caseRefObjFlushPost = reactive({
  info: {
    name: 'IA',
    age: 100,
  },
})

watch(
  caseRefObjFlushPre,
  (newVal, oldVal) => {
    console.log('caseRefObjFlushPre newVal: ', newVal)
    console.log('caseRefObjFlushPre oldVal: ', oldVal)
  },
  {
    flush: 'pre', // pre:组件更新前执行; sync: 组件同步执行 ; post: 组件更新后执行
  },
)

watch(
  caseRefObjFlushSync,
  (newVal, oldVal) => {
    console.log('caseRefObjFlushSync newVal: ', newVal)
    console.log('caseRefObjFlushSync oldVal: ', oldVal)
  },
  {
    flush: 'sync', // pre:组件更新前执行; sync: 组件同步执行 ; post: 组件更新后执行
  },
)

watch(
  caseRefObjFlushPost,
  (newVal, oldVal) => {
    console.log('caseRefObjFlushPost newVal: ', newVal)
    console.log('caseRefObjFlushPost oldVal: ', oldVal)
  },
  {
    flush: 'post', // pre:组件更新前执行; sync: 组件同步执行 ; post: 组件更新后执行
  },
)
</script>
<style scoped>
hr {
  margin: 10px 0;
}
</style>
